package org.jeecg.modules.basic.unit.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.FillRuleConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.vo.DictModel;
import org.jeecg.common.util.FillRuleUtil;
import org.jeecg.modules.basic.customer.entity.BasicCustomer;
import org.jeecg.modules.basic.material.entity.BasicMaterial;
import org.jeecg.modules.basic.material.mapper.BasicMaterialMapper;
import org.jeecg.modules.basic.materialtype.entity.BasicMaterialTreeVO;
import org.jeecg.modules.basic.unit.entity.BasicUnit;
import org.jeecg.modules.basic.unit.mapper.BasicUnitMapper;
import org.jeecg.modules.basic.unit.service.IBasicUnitService;
import org.jeecgframework.poi.excel.ExcelImportUtil;
import org.jeecgframework.poi.excel.entity.ImportParams;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 计量单位
 * @Author: jeecg-boot
 * @Date:   2023-07-26
 * @Version: V1.0
 */
@Service
public class BasicUnitServiceImpl extends ServiceImpl<BasicUnitMapper, BasicUnit> implements IBasicUnitService {

    @Autowired
    private BasicUnitMapper basicUnitMapper;

    @Autowired
    private BasicMaterialMapper materialMapper;

    /**
     * 查询父计量单位
     * @return
     */
    @Override
    public List<BasicUnit> listParent(String name) {
        List<BasicUnit> list = this.list(new LambdaQueryWrapper<BasicUnit>()
                .isNull(BasicUnit::getPid)
                .eq(BasicUnit::getType, 1)
                .like(StringUtils.isNotBlank(name), BasicUnit::getName, name));
        return list;
    }

    /**
     * 查询计量单位
     * @return
     */
    @Override
    public Page<BasicUnit> pageChild(Page<BasicUnit> page, BasicUnit unit) {
        List<BasicUnit> pageList = basicUnitMapper.pageChild(page, unit);
        pageList.forEach(a -> {
            a.setStatus_dictText("1".equals(a.getStatus()) ? "启用" : "0".equals(a.getStatus()) ? "禁用" : "");
        });
        return page.setRecords(pageList);
    }

    /**
     * 通过id删除
     * @param id
     */
    @Override
    public void deleteUnitById(String id) {
        List<BasicUnit> list = this.list(new LambdaQueryWrapper<BasicUnit>().eq(BasicUnit::getPid, id).eq(BasicUnit::getDelFlag, 0));
        if (CollectionUtils.isNotEmpty(list)) {
            throw new JeecgBootException("该分组下有子项信息，不可删除！");
        }
        this.removeById(id);
    }

    /**
     * 查询树形结构所有数据
     * @return
     */
    @Override
    public List<BasicMaterialTreeVO> listTree() {
        List<BasicUnit> list = this.list(new LambdaQueryWrapper<BasicUnit>()
                .isNull(BasicUnit::getPid));
        List<BasicMaterialTreeVO> treeVOList = new ArrayList<>();
        for (BasicUnit unit : list) {
            BasicMaterialTreeVO vo = new BasicMaterialTreeVO();
            vo.setId(unit.getId());
            vo.setName(unit.getName());
            vo.setType(unit.getType());
            if (unit.getType() == 1) {
                List<BasicUnit> childList = this.list(new LambdaQueryWrapper<BasicUnit>()
                        .eq(BasicUnit::getPid, unit.getId())
                        .eq(BasicUnit::getStatus, "1"));
                List<BasicMaterialTreeVO> treeVOS = new ArrayList<>();
                for (BasicUnit basicUnit : childList) {
                    BasicMaterialTreeVO childVO = new BasicMaterialTreeVO();
                    childVO.setId(basicUnit.getId());
                    childVO.setName(basicUnit.getName());
                    childVO.setType(basicUnit.getType());
                    childVO.setChildren(Collections.emptyList());
                    treeVOS.add(childVO);
                }
                vo.setChildren(treeVOS);
            } else {
                vo.setChildren(Collections.emptyList());
            }
            treeVOList.add(vo);
        }
        List<BasicMaterialTreeVO> collect = treeVOList.stream().sorted(Comparator.comparing(BasicMaterialTreeVO::getType)).collect(Collectors.toList());
        return collect;
    }

    /**
     * 导入
     * @param request
     * @return
     */
    @Override
    public Result<String> importExcel(HttpServletRequest request) {
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        Map<String, MultipartFile> fileMap = multipartRequest.getFileMap();
        for (Map.Entry<String, MultipartFile> entity : fileMap.entrySet()) {
            // 获取上传文件对象
            MultipartFile file = entity.getValue();
            ImportParams params = new ImportParams();
            params.setTitleRows(2);
            params.setHeadRows(1);
            params.setNeedSave(true);
            try {
                List<BasicUnit> list = ExcelImportUtil.importExcel(file.getInputStream(), BasicUnit.class, params);
                for (BasicUnit unit : list) {
                    if (StringUtils.isBlank(unit.getName())) {
                        return Result.error("文件导入失败:名称不能为空！");
                    }
                    if (StringUtils.isBlank(unit.getCode())) {
                        return Result.error("文件导入失败:编码不能为空！");
                    }
                    if (StringUtils.isBlank(unit.getStatus()) && StringUtils.isNotBlank(unit.getPid())) {
                        return Result.error("文件导入失败:状态不能为空！");
                    }
                    if (!"0".equals(unit.getStatus()) && !"1".equals(unit.getStatus()) && StringUtils.isNotBlank(unit.getPid())) {
                        return Result.error("文件导入失败:状态只能填启用或禁用！");
                    }
                    List<BasicUnit> names = this.list(new LambdaQueryWrapper<BasicUnit>()
                            .eq(BasicUnit::getName, unit.getName()));
                    if (CollectionUtil.isNotEmpty(names)) {
                        return Result.error("文件导入失败:名称 "+unit.getName()+" 系统中已存在！");
                    }
                    List<BasicUnit> codes = this.list(new LambdaQueryWrapper<BasicUnit>()
                            .eq(BasicUnit::getCode, unit.getCode()));
                    if (CollectionUtil.isNotEmpty(codes)) {
                        return Result.error("文件导入失败:编码 "+unit.getCode()+" 系统中已存在！");
                    }
                }
                this.saveBatch(list);
                return Result.OK("文件导入成功！数据行数：" + list.size());
            } catch (Exception e) {
                String msg = e.getMessage();
                log.error(msg, e);
                if(msg!=null && msg.indexOf("Duplicate entry")>=0){
                    return Result.error("文件导入失败:有重复数据！");
                }else{
                    return Result.error("文件导入失败:" + e.getMessage());
                }
            } finally {
                try {
                    file.getInputStream().close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return Result.error("文件导入失败！");
    }

    /**
     * 分页查询所有子计量单位
     * @param page
     * @param unit
     * @return
     */
    @Override
    public Page<BasicUnit> allChild(Page<BasicUnit> page, BasicUnit unit) {
        List<BasicUnit> pageList = basicUnitMapper.allChild(page, unit);
        pageList.forEach(a -> {
            a.setStatus_dictText("1".equals(a.getStatus()) ? "启用" : "0".equals(a.getStatus()) ? "禁用" : "");
        });
        return page.setRecords(pageList);
    }

    @Override
    public void updateUsed(List<String> unitIds) {
        if (CollectionUtil.isEmpty(unitIds)){
            return;
        }
        for (String id : unitIds) {
            Long aLong = materialMapper.selectCount(new LambdaQueryWrapper<BasicMaterial>()
                    .eq(BasicMaterial::getAssistantUnitId, id)
                    .or().eq(BasicMaterial::getInventoryUnitId, id));
            BasicUnit basicUnit = new BasicUnit();
            basicUnit.setId(id);
            basicUnit.setUsed(Math.toIntExact(aLong));
            basicUnitMapper.updateById(basicUnit);
        }
    }

    @Async
    @Override
    public void updateUsedAll() {
        List<BasicMaterial> materials = materialMapper.selectList(new QueryWrapper<BasicMaterial>());

        for (BasicMaterial material : materials) {
            ArrayList<String> unitIds = new ArrayList<>();
            unitIds.add(material.getInventoryUnitId());
            unitIds.add(material.getAssistantUnitId());
            updateUsed(unitIds);
        }
    }

    @Override
    public Map<String, String> getIdByCodes(List<String> list) {
        if(CollectionUtil.isEmpty(list)){
            return MapUtil.empty();
        }
        List<BasicUnit> pageList = basicUnitMapper.selectList(new LambdaQueryWrapper<BasicUnit>().in(BasicUnit::getCode,list));
        if(CollectionUtil.isEmpty(pageList)){
            return MapUtil.empty();
        }
        Map<String, String> collect = pageList.stream().collect(Collectors.toMap(a -> a.getCode(), t -> t.getId()));
        return collect;
    }
}
